home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / cross / dasm202.lha / dasm-2.02 / main.c < prev    next >
C/C++ Source or Header  |  1995-03-08  |  19KB  |  935 lines

  1.  
  2. /*
  3.  *  MAIN.C
  4.  *
  5.  *  DASM   sourcefile
  6.  *
  7.  *  NOTE: must handle mnemonic extensions and expression decode/compare.
  8.  */
  9.  
  10. #include "asm.h"
  11.  
  12. #define MAXLINE 256
  13. #define ISEGNAME    "code"
  14.  
  15. void cleanup(char *buf);
  16. MNE *parse(char *buf);
  17. void panic(char *str);
  18. MNE *findmne(char *str);
  19. void clearsegs(void);
  20. void clearrefs(void);
  21.  
  22. static uword hash1(char *str);
  23. static void outlistfile(void);
  24.  
  25. uword _fmode = 0;    /*  was trying to port to 16 bit IBM-PC lattice C */
  26.              /*      but failed    */
  27.  
  28. ubyte     Disable_me;
  29. ubyte     StopAtEnd = 0;
  30. char     *Extstr;
  31. ubyte     Listing = 1;
  32.  
  33. int
  34. main(int ac, char **av)
  35. {
  36.     char buf[MAXLINE];
  37.     int pass, i;
  38.     MNE *mne;
  39.     ulong oldredo = -1;
  40.     ulong oldwhy = 0;
  41.     ulong oldeval = 0;
  42.  
  43.     addhashtable(Ops);
  44.     pass = 1;
  45.  
  46.     if (ac < 2) {
  47. fail:
  48. #if Olaf
  49.         puts("DASM V2.02, high level Macro Assembler");
  50. #else
  51.         puts("DASM V2.00, high level Macro Assembler");
  52. #endif
  53.         puts("(C)Copyright 1988 by Matthew Dillon, All Rights Reserved");
  54.         puts("redistributable for non-profit only");
  55.         puts("");
  56.         puts("DASM sourcefile [options]");
  57.         puts(" -f#      output format");
  58.         puts(" -oname   output file");
  59.         puts(" -lname   list file");
  60.         puts(" -sname   symbol dump");
  61.         puts(" -v#      verboseness");
  62.         puts(" -Dname=exp   define label");
  63. #if Olaf
  64.         puts(" -Vname=exp   define label as in EQM");
  65.         puts(" -<       Swap < and > (to be backwards compatible)");
  66. #endif
  67.         exit(1);
  68.     }
  69. #if Olaf
  70.     printf("DASM V2.02, (c)Copyright 1988 Matthew Dillon, All Rights Reserved\n");
  71. #else
  72.     printf("DASM V2.00, (c)Copyright 1988 Matthew Dillon, All Rights Reserved\n");
  73. #endif
  74.     for (i = 2; i < ac; ++i) {
  75.         if (av[i][0] == '-') {
  76.             register char *str = av[i]+2;
  77.             switch(av[i][1]) {
  78.             case 'd':
  79.                 Xdebug = atoi(str);
  80.                 break;
  81. #if OlafM
  82.             case 'M':
  83. #endif
  84.             case 'D':
  85.                 while (*str && *str != '=')
  86.                     ++str;
  87.                 if (*str == '=') {
  88.                     *str = 0;
  89.                     ++str;
  90.                 }
  91.                 else {
  92.                     str = "0";
  93.                 }
  94.                 Av[0] = av[i]+2;
  95. #if OlafM
  96.                 if (av[i][1] == 'M')
  97.                 v_eqm(str, NULL);
  98.                 else
  99. #endif
  100.                 v_set(str, NULL);
  101.                 break;
  102.             case 'f':   /*  F_format    */
  103.                 F_format = atoi(str);
  104.                 if (F_format < 1 || F_format > 3)
  105.                     panic("Illegal format specification");
  106.                 break;
  107.             case 'o':   /*  F_outfile   */
  108.                 F_outfile = str;
  109. nofile:
  110.                 if (*str == 0)
  111.                     panic("need file name for specified option");
  112.                 break;
  113.             case 'l':   /*  F_listfile  */
  114.                 F_listfile = str;
  115.                 goto nofile;
  116.             case 's':   /*  F_symfile   */
  117.                 F_symfile = str;
  118.                 goto nofile;
  119.             case 'v':   /*  F_verbose   */
  120.                 F_verbose = atoi(str);
  121.                 break;
  122.             case 't':   /*  F_temppath  */
  123.                 F_temppath = str;
  124.                 break;
  125. #if OlafLt
  126.             case '<':   /* Swap < and > for stupid compatibility */
  127.                 SwapLessMore = !SwapLessMore;
  128.                 break;
  129. #endif
  130.             default:
  131.                 goto fail;
  132.             }
  133.             continue;
  134.         }
  135.         goto fail;
  136.     }
  137.  
  138. /*      INITIAL SEGMENT */
  139.  
  140.     {
  141.         register SEGMENT *seg = (SEGMENT *)permalloc(sizeof(SEGMENT));
  142.         seg->name = strcpy(permalloc(sizeof(ISEGNAME)), ISEGNAME);
  143.         seg->flags= seg->rflags = seg->initflags = seg->initrflags = SF_UNKNOWN;
  144.         Csegment = Seglist = seg;
  145.     }
  146. /*      TOP LEVEL IF      */
  147.     {
  148.         register IFSTACK *ifs = (IFSTACK *)zmalloc(sizeof(IFSTACK));
  149.         ifs->file = (INCFILE *)-1;
  150.         ifs->flags = IFF_BASE;
  151.         ifs->acctrue = 1;
  152.         ifs->true  = 1;
  153.         Ifstack = ifs;
  154.     }
  155. nextpass:
  156.     Localindex = Lastlocalindex = 0;
  157. #if OlafDol
  158.     Localdollarindex = Lastlocaldollarindex = 0;
  159. #endif
  160.     _fmode = 0x8000;
  161.     FI_temp = fopen(F_outfile, "w");
  162.     _fmode = 0;
  163.     Fisclear = 1;
  164.     if (FI_temp == NULL) {
  165.         printf("unable to [re]open '%s'\n", F_outfile);
  166.         exit(1);
  167.     }
  168.     if (F_listfile) {
  169.         FI_listfile = fopen(F_listfile, "w");
  170.         if (FI_listfile == NULL) {
  171.             printf("unable to [re]open '%s'\n", F_listfile);
  172.             exit(1);
  173.         }
  174.     }
  175.     pushinclude(av[1]);
  176.     while (Incfile) {
  177.     for (;;) {
  178.         if (Incfile->flags & INF_MACRO) {
  179.         if (Incfile->strlist == NULL) {
  180.             Av[0] = "";
  181.             v_mexit(NULL, NULL);
  182.             continue;
  183.         }
  184.         strcpy(buf, Incfile->strlist->buf);
  185.         Incfile->strlist = Incfile->strlist->next;
  186.         }
  187.         else {
  188.         if (fgets(buf, MAXLINE, Incfile->fi) == NULL)
  189.             break;
  190.         }
  191.         cleanup(buf);
  192.         ++Incfile->lineno;
  193.         mne = parse(buf);
  194.         if (Av[1][0]) {
  195.         if (mne) {
  196.             if ((mne->flags & MF_IF) || (Ifstack->true && Ifstack->acctrue))
  197.             (*mne->vect)(Av[2], mne);
  198.         }
  199.         else {
  200.             if (Ifstack->true && Ifstack->acctrue) {
  201.             printf("unknown mnemonic: '%s'\n", Av[1]);
  202.             asmerr(4,0);
  203.             }
  204.         }
  205.         }
  206.         else {
  207.         if (Ifstack->true && Ifstack->acctrue)
  208.             programlabel();
  209.         }
  210.         if (F_listfile)
  211.         outlistfile();
  212.     }
  213.     while (Reploop && Reploop->file == Incfile)
  214.         rmnode((void **)&Reploop, sizeof(REPLOOP));
  215.     while (Ifstack->file == Incfile)
  216.         rmnode((void **)&Ifstack, sizeof(IFSTACK));
  217.     fclose(Incfile->fi);
  218.     free(Incfile->name);
  219.     --Inclevel;
  220.     rmnode((void **)&Incfile, sizeof(INCFILE));
  221.     if (Incfile) {
  222.         /*
  223.         if (F_verbose > 1)
  224.         printf("back to: %s\n", Incfile->name);
  225.         */
  226.         if (F_listfile)
  227.         fprintf(FI_listfile, "------- FILE %s\n", Incfile->name);
  228.     }
  229.     }
  230.     if (F_verbose >= 1) {
  231.     SEGMENT *seg;
  232.     char *bss;
  233.  
  234.     puts("");
  235.     printf("END OF PASS: %d\n", pass);
  236.     puts("Segment---     init-pc  init-rpc finl-pc  finl-rpc");
  237.     for (seg = Seglist; seg; seg = seg->next) {
  238.         bss = (seg->flags & SF_BSS) ? "[u]" : "   ";
  239.         printf("%10s %3s ", seg->name, bss);
  240.         printf("%s %s ", sftos(seg->initorg, seg->initflags), sftos
  241.             (seg->initrorg, seg->initrflags));
  242.         printf("%s %s\n", sftos(seg->org, seg->flags), sftos(seg->rorg,
  243.         seg->rflags));
  244.     }
  245.     printf("Reasons: %4ld,%4ld   Reasoncode: %08lx\n", Redo, Redo_eval,
  246.     Redo_why);
  247.     }
  248.     if (F_verbose >= 3) {
  249.     SYMBOL *sym;
  250.     int i;
  251.  
  252.     if (F_verbose == 3)
  253.         puts("SYMBOLIST:  (Unreferenced and unresolved symbols only)");
  254.     else
  255.         puts("SYMBOLIST");
  256.     for (i = 0; i < SHASHSIZE; ++i) {
  257.         for (sym = SHash[i]; sym; sym = sym->next) {
  258.             if (F_verbose > 3 || (sym->flags & SYM_UNKNOWN) || !(sym->flags &
  259.                 SYM_MASREF))
  260.                 printf("%10s %s\n", sym->name, sftos(sym->value, sym->flags));
  261.         }
  262.     }
  263.     puts("ENDSYMBOLIST");
  264.     }
  265.     closegenerate();
  266.     fclose(FI_temp);
  267.     if (FI_listfile)
  268.     fclose(FI_listfile);
  269.     if (Redo) {
  270.     if (Redo == oldredo && Redo_why == oldwhy && Redo_eval == oldeval) {
  271.         puts("Error: source is not resolvable.");
  272.         if (F_verbose < 2)
  273.         puts("re-run with verbose option 2 or higher to determine problem");
  274.         exit(1);
  275.     }
  276.     oldredo = Redo;
  277.     oldwhy = Redo_why;
  278.     oldeval = Redo_eval;
  279.     Redo = 0;
  280.     Redo_why = 0;
  281.     Redo_eval = 0;
  282.     ++pass;
  283.     if (StopAtEnd) {
  284.         printf("Unrecoverable error in pass, aborting assembly!\n");
  285.     }
  286.     else if (pass > 10) {
  287.         printf("More than 10 passes, something *must* be wrong!\n");
  288.         exit(1);
  289.     }
  290.     else {
  291.         clearrefs();
  292.         clearsegs();
  293.         goto nextpass;
  294.     }
  295.     }
  296.     if (F_symfile) {
  297.     FILE *fi = fopen(F_symfile, "w");
  298.     if (fi) {
  299.         register SYMBOL *sym;
  300.         puts("dumping symbols...");
  301.         for (i = 0; i < SHASHSIZE; ++i) {
  302.         for (sym = SHash[i]; sym; sym = sym->next) {
  303.             fprintf(fi, "%-15s %s", sym->name, sftos(sym->value, sym->flags));
  304.             if (sym->flags & SYM_STRING)
  305.                 fprintf(fi, " \"%s\"", sym->string);
  306.             putc('\n', fi);
  307.         }
  308.         }
  309.         fclose(fi);
  310.     }
  311.     else {
  312.         printf("unable to open symbol dump file '%s'\n", F_symfile);
  313.     }
  314.     }
  315.     return 0;
  316. }
  317.  
  318. static
  319. void
  320. outlistfile(void)
  321. {
  322.     char c;
  323.     char true;
  324.     char *ptr;
  325.     char dot;
  326.     int i;
  327.  
  328.     if (Incfile->flags & INF_NOLIST)
  329.     return;
  330.  
  331.     c = (Pflags & SF_BSS) ? 'U' : ' ';
  332.     true = (Ifstack->true && Ifstack->acctrue) ? ' ' : '-';
  333.     ptr = Extstr;
  334.     dot = ' ';
  335.     if (ptr)
  336.         dot = '.';
  337.     else
  338.         ptr = "";
  339.  
  340.     fprintf(FI_listfile, "%5ld %c%s ",
  341.         Incfile->lineno, c, sftos(Plab, Pflags & 7));
  342.     for (i = 0; i < Glen && i < 4; ++i)
  343.         fprintf(FI_listfile, "%02x ", Gen[i]);
  344.     for (; i < 4; ++i)
  345.         fwrite("   ", 3, 1, FI_listfile);
  346.     fprintf(FI_listfile, "%c%-10s %5s%c%-3s %s\n",
  347.         true, Av[0], Av[1], dot, ptr, Av[2]);
  348.     Glen = 0;
  349.     Extstr = NULL;
  350. }
  351.  
  352.  
  353. char *
  354. sftos(long val, int flags)
  355. {
  356.     static char buf[64];
  357.     static char c;
  358.     register char *ptr = (c) ? buf : buf + 32;
  359.  
  360.     c = 1 - c;
  361.     sprintf(ptr, "%04lx", val);
  362.     if (flags & SYM_UNKNOWN)
  363.         strcpy(ptr, "????");
  364.     if (flags & SYM_STRING)
  365.         strcpy(ptr, "str ");
  366.     if (flags & SYM_MACRO)
  367.         strcpy(ptr, "eqm ");
  368.     strcpy(ptr+4, "    ");
  369.     if (flags & (SYM_MASREF|SYM_SET)) {
  370.         ptr[4] = '(';
  371.         ptr[7] = ')';
  372.     }
  373.     if (flags & (SYM_MASREF))
  374.         ptr[5] = 'r';
  375.     if (flags & (SYM_SET))
  376.         ptr[6] = 's';
  377.     return ptr;
  378. }
  379.  
  380. void
  381. clearsegs(void)
  382. {
  383.     register SEGMENT *seg;
  384.  
  385.     for (seg = Seglist; seg; seg = seg->next) {
  386.         seg->flags = (seg->flags & SF_BSS) | SF_UNKNOWN;
  387.         seg->rflags= seg->initflags = seg->initrflags = SF_UNKNOWN;
  388.     }
  389. }
  390.  
  391. void
  392. clearrefs(void)
  393. {
  394.     register SYMBOL *sym;
  395.     register int i;
  396.  
  397.     for (i = 0; i < SHASHSIZE; ++i)
  398.         for (sym = SHash[i]; sym; sym = sym->next)
  399.             sym->flags &= ~SYM_REF;
  400. }
  401.  
  402. void
  403. cleanup(char *buf)
  404. {
  405.     register char *str;
  406.     register STRLIST *strlist;
  407.     register int arg, add;
  408.  
  409.     for (str = buf; *str; ++str) {
  410.     switch(*str) {
  411.     case '\n':
  412.     case ';':
  413.         goto br2;
  414.     case TAB:
  415.         *str = ' ';
  416.         break;
  417.     case '\'':
  418.         ++str;
  419.         if (*str == TAB)
  420.             *str = ' ';
  421.         if (*str == '\n' || *str == 0) {
  422.             str[0] = ' ';
  423.             str[1] = 0;
  424.         }
  425.         if (str[0] == ' ')
  426.             str[0] = '\x80';
  427.         break;
  428.     case '\"':
  429.         ++str;
  430.         while (*str && *str != '\"') {
  431.             if (*str == ' ')
  432.                 *str = '\x80';
  433.             ++str;
  434.         }
  435.         if (*str != '\"') {
  436.             asmerr(0,0);
  437.             --str;
  438.         }
  439.         break;
  440.     case '{':
  441.         if (Disable_me)
  442.             break;
  443.         if (Xdebug)
  444.             printf("macro tail: '%s'\n", str);
  445.         arg = atoi(str+1);
  446.         for (add = 0; *str && *str != '}'; ++str)
  447.             --add;
  448.         if (*str != '}') {
  449.             puts("end brace required");
  450.             --str;
  451.             break;
  452.         }
  453.         --add;
  454.         ++str;
  455.         if (Xdebug)
  456.             printf("add/str: %d '%s'\n", add, str);
  457.         for (strlist = Incfile->args; arg && strlist;) {
  458.             --arg;
  459.             strlist = strlist->next;
  460.         }
  461.         if (strlist) {
  462.             add += strlen(strlist->buf);
  463.             if (Xdebug)
  464.                 printf("strlist: '%s' %ld\n", strlist->buf, (long)strlen(strlist->buf));
  465.             if (str + add + strlen(str) + 1 > buf + MAXLINE) {
  466.             if (Xdebug)
  467.                 printf("str %8ld buf %8ld (add/strlen(str)): %d %ld\n", (long)str, (long)buf,
  468.                 add, (long)strlen(str));
  469.             panic("failure1");
  470.             }
  471.             memmove(str + add, str, strlen(str)+1);
  472.             str += add;
  473.             if (str - strlen(strlist->buf) < buf)
  474.             panic("failure2");
  475.             memmove(str - strlen(strlist->buf), strlist->buf, strlen(strlist->buf));
  476.             str -= strlen(strlist->buf);
  477.             if (str < buf || str >= buf + MAXLINE)
  478.             panic("failure 3");
  479.             --str;    /*  for loop increments string    */
  480.         }
  481.         else {
  482.             asmerr(7,0);
  483.             goto br2;
  484.         }
  485.         break;
  486.         }
  487.     }
  488. br2:
  489.     while(str != buf && *(str-1) == ' ')
  490.     --str;
  491.     *str = 0;
  492. }
  493.  
  494. void
  495. panic(char *str)
  496. {
  497.     puts(str);
  498.     exit(1);
  499. }
  500.  
  501. /*
  502.  *  .dir    direct              x
  503.  *  .ext    extended              x
  504.  *  .r          relative              x
  505.  *  .x          index, no offset          x
  506.  *  .x8     index, byte offset          x
  507.  *  .x16    index, word offset          x
  508.  *  .bit    bit set/clr
  509.  *  .bbr    bit and branch
  510.  *  .imp    implied (inherent)          x
  511.  *  .b                      x
  512.  *  .w                      x
  513.  *  .l                      x
  514.  *  .u                      x
  515.  */
  516.  
  517.  
  518. void
  519. findext(char *str)
  520. {
  521.     Mnext = -1;
  522.     Extstr = NULL;
  523. #if OlafDotop
  524.     if (str[0] == '.') {    /* Allow .OP for OP */
  525.         return;
  526.     }
  527. #endif
  528.     while (*str && *str != '.')
  529.         ++str;
  530.     if (*str) {
  531.         *str = 0;
  532.         ++str;
  533.         Extstr = str;
  534.         switch(str[0]|0x20) {
  535.         case '0':
  536.         case 'i':
  537.             Mnext = AM_IMP;
  538.             switch(str[1]|0x20) {
  539.             case 'x':
  540.                 Mnext = AM_0X;
  541.                 break;
  542.             case 'y':
  543.                 Mnext = AM_0Y;
  544.                 break;
  545.             case 'n':
  546.                 Mnext = AM_INDWORD;
  547.                 break;
  548.             }
  549.             return;
  550.         case 'd':
  551.         case 'b':
  552.         case 'z':
  553.             switch(str[1]|0x20) {
  554.             case 'x':
  555.                 Mnext = AM_BYTEADRX;
  556.                 break;
  557.             case 'y':
  558.                 Mnext = AM_BYTEADRY;
  559.                 break;
  560.             case 'i':
  561.                 Mnext = AM_BITMOD;
  562.                 break;
  563.             case 'b':
  564.                 Mnext = AM_BITBRAMOD;
  565.                 break;
  566.             default:
  567.                 Mnext = AM_BYTEADR;
  568.                 break;
  569.             }
  570.             return;
  571.         case 'e':
  572.         case 'w':
  573.         case 'a':
  574.             switch(str[1]|0x20) {
  575.             case 'x':
  576.                 Mnext = AM_WORDADRX;
  577.                 break;
  578.             case 'y':
  579.                 Mnext = AM_WORDADRY;
  580.                 break;
  581.             default:
  582.                 Mnext = AM_WORDADR;
  583.                 break;
  584.             }
  585.             return;
  586.         case 'l':
  587.             Mnext = AM_LONG;
  588.             return;
  589.         case 'r':
  590.             Mnext = AM_REL;
  591.             return;
  592.         case 'u':
  593.             Mnext = AM_BSS;
  594.             return;
  595.         }
  596.     }
  597. }
  598.  
  599. /*
  600.  *  bytes arg will eventually be used to implement a linked list of free
  601.  *  nodes.
  602.  *  Assumes *base is really a pointer to a structure with .next as the first
  603.  *  member.
  604.  */
  605.  
  606. void
  607. rmnode(void **base, int bytes)
  608. {
  609.     void *node;
  610.  
  611.     if ((node = *base) != NULL) {
  612.         *base = *(void **)node;
  613.         free(node);
  614.     }
  615. }
  616.  
  617. /*
  618.  *  Parse into three arguments: Av[0], Av[1], Av[2]
  619.  */
  620. MNE *
  621. parse(char *buf)
  622. {
  623.     register int i, j;
  624.     MNE *mne = NULL;
  625.  
  626.     i = 0;
  627.     j = 1;
  628. #if OlafFreeFormat
  629.     /* Skip all initial spaces */
  630.     while (buf[i] == ' ')
  631.     ++i;
  632. #endif
  633. #if OlafHashFormat
  634.     /*
  635.      * If the first non-space is a ^, skip all further spaces too.
  636.      * This means what follows is a label.
  637.      * If the first non-space is a #, what follows is a directive/opcode.
  638.      */
  639.     while (buf[i] == ' ')
  640.     ++i;
  641.     if (buf[i] == '^') {
  642.     ++i;
  643.     while (buf[i] == ' ')
  644.         ++i;
  645.     } else if (buf[i] == '#') {
  646.     buf[i] = ' ';    /* label separator */
  647.     } else
  648.     i = 0;
  649. #endif
  650.     Av[0] = Avbuf + j;
  651.     while (buf[i] && buf[i] != ' ') {
  652.     if (buf[i] == ':') {/*OIS*/
  653.         i++;
  654.         break;        /*OIS*/
  655.     }
  656.     if ((unsigned char)buf[i] == 0x80)
  657.         buf[i] = ' ';
  658.     Avbuf[j++] = buf[i++];
  659.     }
  660.     Avbuf[j++] = 0;
  661. #if OlafFreeFormat
  662.     /* Try if the first word is an opcode */
  663.     findext(Av[0]);
  664.     mne = findmne(Av[0]);
  665.     if (mne != NULL) {
  666.     /* Yes, it is. So there is no label, and the rest
  667.      * of the line is the argument
  668.      */
  669.     Avbuf[0] = 0;    /* Make an empty string */
  670.     Av[1] = Av[0];    /* The opcode is the previous first word */
  671.     Av[0] = Avbuf;    /* Point the label to the empty string */
  672.     } else
  673. #endif
  674.     {    /* Parse the second word of the line */
  675.     while (buf[i] == ' ')
  676.         ++i;
  677.     Av[1] = Avbuf + j;
  678.     while (buf[i] && buf[i] != ' ') {
  679.         if ((unsigned char)buf[i] == 0x80)
  680.         buf[i] = ' ';
  681.         Avbuf[j++] = buf[i++];
  682.     }
  683.     Avbuf[j++] = 0;
  684.     /* and analyse it as an opcode */
  685.     findext(Av[1]);
  686.     mne = findmne(Av[1]);
  687.     }
  688.     /* Parse the rest of the line */
  689.     while (buf[i] == ' ')
  690.     ++i;
  691.     Av[2] = Avbuf + j;
  692.     while (buf[i]) {
  693.     if (buf[i] == ' ') {
  694.         while(buf[i+1] == ' ')
  695.         ++i;
  696.     }
  697.     if ((unsigned char)buf[i] == 0x80)
  698.         buf[i] = ' ';
  699.     Avbuf[j++] = buf[i++];
  700.     }
  701.     Avbuf[j] = 0;
  702.  
  703.     return mne;
  704. }
  705.  
  706.  
  707.  
  708. MNE *
  709. findmne(char *str)
  710. {
  711.     register int i;
  712.     register char c;
  713.     register MNE *mne;
  714.     char buf[64];
  715.  
  716. #if OlafDotop
  717.     if (str[0] == '.') {    /* Allow .OP for OP */
  718.         str++;
  719.     }
  720. #endif
  721.     for (i = 0; (c = str[i]); ++i) {
  722.         if (c >= 'A' && c <= 'Z')
  723.             c += 'a' - 'A';
  724.         buf[i] = c;
  725.     }
  726.     buf[i] = 0;
  727.     for (mne = MHash[hash1(buf)]; mne; mne = mne->next) {
  728.         if (strcmp(buf, mne->name) == 0)
  729.             break;
  730.     }
  731.     return(mne);
  732. }
  733.  
  734. void
  735. v_macro(char *str, MNE *dummy)
  736. {
  737.     STRLIST *base;
  738.     ubyte defined = 0;
  739.     register STRLIST **slp, *sl;
  740.     register MACRO *mac;
  741.     register MNE   *mne;
  742.     register uword i;
  743.     char buf[MAXLINE];
  744.     ubyte skipit = !(Ifstack->true && Ifstack->acctrue);
  745.  
  746.     if (skipit) {
  747.         defined = 1;
  748.     }
  749.     else {
  750.         defined = (findmne(str) != NULL);
  751.         if (F_listfile)
  752.             outlistfile();
  753.     }
  754.     if (!defined) {
  755.         base = NULL;
  756.         slp = &base;
  757.         mac = (MACRO *)permalloc(sizeof(MACRO));
  758.         i = hash1(str);
  759.         mac->next = (void *)MHash[i];
  760.         mac->vect = v_execmac;
  761.         mac->name = strcpy(permalloc(strlen(str)+1), str);
  762.         mac->flags = MF_MACRO;
  763.         MHash[i] = (void *)mac;
  764.     }
  765.     while (fgets(buf, MAXLINE, Incfile->fi)) {
  766.         ++Incfile->lineno;
  767.         Disable_me = 1;
  768.         cleanup(buf);
  769.         Disable_me = 0;
  770.         mne = parse(buf);
  771.         if (Av[1][0]) {
  772.             if (mne && mne->vect == v_endm) {
  773.                 if (!defined)
  774.                     mac->strlist = base;
  775.                 return;
  776.             }
  777.         }
  778.         if (!skipit && F_listfile)
  779.             outlistfile();
  780.         if (!defined) {
  781.             sl = (STRLIST *)permalloc(5+strlen(buf));
  782.             strcpy(sl->buf, buf);
  783.             *slp = sl;
  784.             slp = &sl->next;
  785.         }
  786.     }
  787.     asmerr(8,1);
  788. }
  789.  
  790.  
  791. void
  792. addhashtable(MNE *mne)
  793. {
  794.     register int i, j;
  795.     ubyte opcode[NUMOC];
  796.  
  797.     for (; mne->vect; ++mne) {
  798.         memcpy(opcode, mne->opcode, NUMOC);
  799.         for (i = j = 0; i < NUMOC; ++i) {
  800.             mne->opcode[i] = 0;    /* not really needed */
  801.             if (mne->okmask & (1 << i))
  802.                 mne->opcode[i] = opcode[j++];
  803.         }
  804.         i = hash1(mne->name);
  805.         mne->next = MHash[i];
  806.         MHash[i] = mne;
  807.     }
  808. }
  809.  
  810.  
  811. static uword
  812. hash1(char *str)
  813. {
  814.     register uword result = 0;
  815.  
  816.     while (*str)
  817.         result = (result << 2) ^ *str++;
  818.     return(result & MHASHAND);
  819. }
  820.  
  821. int
  822. pushinclude(char *str)
  823. {
  824.     register INCFILE *inf;
  825.     register FILE *fi;
  826.  
  827.     if ((fi = fopen(str, "r")) != NULL) {
  828.         if (F_verbose > 1)
  829.             printf("%.*sInclude: %s\n", Inclevel*4, "", str);
  830.         ++Inclevel;
  831.         if (F_listfile)
  832.             fprintf(FI_listfile, "------- FILE %s\n", str);
  833.         inf = (INCFILE *)zmalloc(sizeof(INCFILE));
  834.         inf->next    = Incfile;
  835.         inf->name    = strcpy(malloc(strlen(str)+1), str);
  836.         inf->fi = fi;
  837.         inf->lineno = 0;
  838.         Incfile = inf;
  839.         return(1);
  840.     }
  841.     printf("unable to open %s\n", str);
  842.     return 0;
  843. }
  844.  
  845. char Stopend[] = {
  846.     1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1,1
  847. };
  848.  
  849. char *Errors[] = {
  850.     "Syntax Error",
  851.     "Expression table overflow",
  852.     "Unbalanced Braces []",
  853.     "Division by zero",
  854.     "Unknown Mnemonic",
  855.     "Illegal Addressing mode",
  856.     "Illegal forced Addressing mode",   /*  nu  */
  857.     "Not enough args passed to Macro",
  858.     "Premature EOF",
  859.     "Illegal character",
  860.     "Branch out of range",
  861.     "ERR pseudo-op encountered",
  862.     "Origin Reverse-indexed",           /*  12  */
  863.     "EQU: Value mismatch",
  864.     "Address must be <$100",            /*  nu  */
  865.     "Illegal bit specification",
  866.     "Not enough args",                  /*  16  */
  867.     "Label Mismatch",                   /*  17  */
  868.     "Value Undefined",
  869.     "Illegal Forced Address mode",      /*  19  */
  870.     "Processor not supported",          /*  20  */
  871.     NULL
  872. };
  873.  
  874. void
  875. asmerr(int err, int abort)
  876. {
  877.     char *str;
  878.     INCFILE *incfile;
  879.  
  880.     if (Stopend[err])
  881.         StopAtEnd = 1;
  882.     for (incfile = Incfile; incfile->flags & INF_MACRO; incfile=incfile->next);
  883.     str = Errors[err];
  884.     if (F_listfile)
  885.         fprintf(FI_listfile, "*line %4ld %-10s %s\n", incfile->lineno,
  886.         incfile->name, str);
  887.     printf("line %4ld %-10s %s\n", incfile->lineno, incfile->name, str);
  888.     if (abort) {
  889.         puts("Aborting assembly");
  890.         if (F_listfile)
  891.             fputs("Aborting assembly\n", FI_listfile);
  892.         exit(1);
  893.     }
  894. }
  895.  
  896. char *
  897. zmalloc(int bytes)
  898. {
  899.     char *ptr = malloc(bytes);
  900.     if (ptr) {
  901.         memset(ptr, 0, bytes);
  902.         return(ptr);
  903.     }
  904.     panic("unable to malloc");
  905.     return NULL;
  906. }
  907.  
  908. char *
  909. permalloc(int bytes)
  910. {
  911.     static char *buf;
  912.     static int left;
  913.     char *ptr;
  914.     /* Assume sizeof(union align) is a power of 2 */
  915.     union align {
  916.         long l;
  917.         void *p;
  918.         void (*fp)(void);
  919.     };
  920.  
  921.     bytes = (bytes + sizeof(union align)-1) & ~(sizeof(union align)-1);
  922.     if (bytes > left) {
  923.         if ((buf = malloc(ALLOCSIZE)) == NULL)
  924.             panic("unable to malloc");
  925.         memset(buf, 0, ALLOCSIZE);
  926.         left = ALLOCSIZE;
  927.         if (bytes > left)
  928.             panic("software error");
  929.     }
  930.     ptr = buf;
  931.     buf += bytes;
  932.     left -= bytes;
  933.     return(ptr);
  934. }
  935.